from glob import glob
from random import choice

from kivy.core.audio import SoundLoader

from kivyx.widgets import Widget
from utils.misc import separate_thread


class SoundPlayer(Widget):
    """A simple sound player with sound event handling."""
    sound_cache = {}

    def __init__(self):
        Widget.__init__(self)
        self.playing = None

        self.register_event_type("on_stop")
        self.register_event_type("on_start")

    def load_sound(self, filename, use_cache=True):
        if use_cache and filename in SoundPlayer.sound_cache:
            return SoundPlayer.sound_cache[filename]
        sound = SoundLoader.load(filename)
        if use_cache:
            SoundPlayer.sound_cache[filename] = sound
        return sound

    @separate_thread
    def play(self, filename, use_cache=True, volume=1.0):
        if self.playing is not None:
            self.stop()

        self.playing = self.load_sound(filename, use_cache=use_cache)
        if self.playing is None:
            return

        self.playing.volume = volume
        self.playing.play()
        self.playing.bind(on_stop=self.stop)
        self.dispatch("on_start")

    def stop(self, *args):
        if self.playing is None:
            return

        if self.playing.state != "stop":
            self.playing.stop()
        self.playing = None
        self.dispatch("on_stop")

    def on_stop(self, *args):
        """Default handler."""
        pass

    def on_start(self, *args):
        """Default handler."""
        pass


class ShuffleSoundPlayer(Widget):
    def __init__(self, sound_directory, extension, volume=1.0):
        Widget.__init__(self)
        self.sound_directory = sound_directory
        self.extension = extension
        self._volume = volume
        self.sound_player = SoundPlayer()

    @property
    def volume(self):
        return self._volume

    @volume.setter
    def volume(self, value):
        self._volume = value
        if self.sound_player.playing is not None:
            self.sound_player.playing.volume = value

    def start(self):
        if self.sound_player.playing is not None:
            return

        self.sound_player.bind(on_stop=self._play_random)
        self._play_random()

    def stop(self):
        if self.sound_player.playing is not None:
            self.sound_player.unbind(on_stop=self._play_random)
            self.sound_player.stop()

    def _play_random(self, *args):
        if self.sound_player.playing is None:
            filename = choice(glob(self.sound_directory + self.extension))
            self.sound_player.play(filename, volume=self.volume)
